package org.groovyflow.spring.web;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.groovyflow.interceptor.RailsStyleInterceptorLogic;

public abstract class AbstractDynamicFinder implements DynamicFinder{
	private String ctrlrPackage;
	private InterceptorHandler beforeHandler;
	private InterceptorHandler afterHandler;
	private InterceptorCache interceptorCache;
	
	
	protected abstract List findObjectAndMethod(HttpServletRequest request, 
			HttpServletResponse response, 
			ClassLoader classLoader);	
	
	public abstract boolean isPrettyURLScheme();
	
	public Object invoke(HttpServletRequest request, HttpServletResponse response, ClassLoader classLoader){
		List objectAndMethod = findObjectAndMethod(request, response, classLoader);
		Object theController = objectAndMethod.get(0);
		Method method = (Method) objectAndMethod.get(1);
		String methName = method.getName();

		try{
			this.beforeHandler.intercept(theController, methName, request, response, null);
			Object ret = method.invoke(theController, request, response);
			this.afterHandler.intercept(theController, methName, request, response, ret);
			return ret;
		}catch(Exception ex){
			ex.printStackTrace();
			throw new RuntimeException(ex);
		}
		
	}	
	

	protected String findControlString(HttpServletRequest request){
		return request.getServletPath();
	}
	protected Method findMethod(Class clazz, String methName) {
		Method[] methods = clazz.getMethods();
		Method theMethod = null;
		for(int i = 0; i < methods.length; i++){
			Method method = methods[i];
			if(method.getName().equals(methName)){
				theMethod = method;
				break;
			}
		}
		if(theMethod == null)
			throw new RuntimeException(clazz + " has no " + methName + " method.");
		return theMethod;
	}
	protected Class findClass(String className, ClassLoader classLoader) {
		try{
			return Class.forName(className, true, classLoader) ;
			//Class clazz = getClass().getClassLoader().loadClass(className, true);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new RuntimeException(ex);
		}
	}
	public Object instantiate(Class clazz){
		try {
			return clazz.newInstance();
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new RuntimeException(ex);
		}
	}
	protected String putClassNameTogether(String raw){
		String className = raw.substring(0, 1).toUpperCase() + raw.substring(1);
		String dot = (this.getCtrlrPackage() == null || this.getCtrlrPackage().equals("")) ? "" : ".";
		className = this.getCtrlrPackage() + dot + className + CONTROLLER_SUFFIX;
		return className;
	}

	public void setBeforeHandler(InterceptorHandler beforeHandler) {
		this.beforeHandler = beforeHandler;
	}
	
	public void setupInterceptorHandlers(){
		this.beforeHandler = new StandardInterceptorHandler();
		this.beforeHandler.setInterceptorLogic(new RailsStyleInterceptorLogic("before", "skipBefore"));
		this.beforeHandler.setDoingBefore(true);
		this.beforeHandler.setInterceptorCache(this.interceptorCache);

		this.afterHandler = new StandardInterceptorHandler();
		this.afterHandler.setInterceptorLogic(new RailsStyleInterceptorLogic("after", "skipAfter"));
		this.afterHandler.setInterceptorCache(this.interceptorCache);
	}
	public void setInterceptorCache(InterceptorCache interceptorCache) {
		this.interceptorCache = interceptorCache;
	}	
	

	public String getCtrlrPackage() {
		return ctrlrPackage;
	}

	public void setCtrlrPackage(String ctrlPackage) {
		this.ctrlrPackage = ctrlPackage;
	}

}
